package hi;

import hi.Hiout.MousePoint;
import hi.Hiout.TrackData;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

public class Connector implements ConnectorInterface {
	static int portnum = 24312; //randomly chosen
	private boolean connected = false;
	List<TrackDataListener> primaryListeners = new ArrayList<TrackDataListener>();
	List<TrackDataListener> fullListeners = new ArrayList<TrackDataListener>();

	public Connector() {}
	
	@Override
	public boolean isConnected() {
		return connected;
	}
	
	@Override
	public void disconnect() {
		connected = false;
	}
	
	private class ThreadConnector extends Thread {
		public void run() {
			Socket trackerSocket = null;
	        try {
				trackerSocket = new Socket(InetAddress.getLocalHost(), portnum);
				InputStream inStream = trackerSocket.getInputStream();
				connected = true;
				while (connected) {
					TrackData trackData = TrackData.parseDelimitedFrom(inStream);
					if (trackData == null) {
						System.err.println("Lost connection to feed.");
						System.exit(1);
					}
					//System.out.println("active="+trackData.getActive()+" x="+trackData.getX()+" y="+trackData.getY());
					MousePoint primaryMouse = trackData.getPrimary();
					if (trackData.hasSecondary()) {
						MousePoint secondaryMouse = trackData.getSecondary();
						for(TrackDataListener fullListener : fullListeners) {
							fullListener.setState(primaryMouse.getActive(), primaryMouse.getX(), primaryMouse.getY(), secondaryMouse.getActive(), secondaryMouse.getX(), secondaryMouse.getY());
						}
					} else {
						for(TrackDataListener fullListener : fullListeners) {
							fullListener.setState(primaryMouse.getActive(), primaryMouse.getX(), primaryMouse.getY());
						}
					}
					for(TrackDataListener primaryListener : primaryListeners) {
						primaryListener.setState(primaryMouse.getActive(), primaryMouse.getX(), primaryMouse.getY());
					}
				}
			} catch (UnknownHostException e) {
	            System.err.println("Can't find localhost");
	            //System.exit(1);
	        } catch (IOException e) {
	            System.err.println("Couldn't get I/O for "
	                               + "the connection to localhost.");
	            //System.exit(1);
	        } finally {
	        	connected = false;
				if (trackerSocket != null) {
					try {
						trackerSocket.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
	
	@Override
	public void connect() {
		if (!connected) {
			Thread runner = new ThreadConnector();
			runner.start();
		}
	}
	
	public void addPrimaryListener(TrackDataListener listener) {
		primaryListeners.add(listener);
	}

	public void removePrimaryListener(TrackDataListener listener) {
		primaryListeners.remove(listener);
	}
	
	public void addFullListener(TrackDataListener listener) {
		fullListeners.add(listener);
	}

	public void removeFullListener(TrackDataListener listener) {
		fullListeners.remove(listener);
	}
}
